home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 039a / mawk10.zip / JMP.C < prev    next >
C/C++ Source or Header  |  1991-10-05  |  6KB  |  235 lines

  1.  
  2. /********************************************
  3. jmp.c
  4. copyright 1991, Michael D. Brennan
  5.  
  6. This is a source file for mawk, an implementation of
  7. the AWK programming language.
  8.  
  9. Mawk is distributed without warranty under the terms of
  10. the GNU General Public License, version 2, 1991.
  11. ********************************************/
  12.  
  13. /* $Log:    jmp.c,v $
  14.  * Revision 3.3.1.1  91/09/14  17:23:33  brennan
  15.  * VERSION 1.0
  16.  * 
  17.  * Revision 3.3  91/08/13  06:51:38  brennan
  18.  * VERSION .9994
  19.  * 
  20.  * Revision 3.2  91/06/28  04:16:53  brennan
  21.  * VERSION 0.999
  22.  * 
  23.  * Revision 3.1  91/06/07  10:27:42  brennan
  24.  * VERSION 0.995
  25.  * 
  26.  * Revision 2.2  91/05/22  07:30:39  brennan
  27.  * fixed stack underflow checks to work correctly on large model DOS
  28.  * 
  29.  * Revision 2.1  91/04/08  08:23:19  brennan
  30.  * VERSION 0.97
  31.  * 
  32. */
  33.  
  34. /* this module deals with back patching jumps, breaks and continues,
  35.    and with save and restoring code when we move code.
  36.    There are three stacks.  If we encounter a compile error, the
  37.    stacks are frozen, i.e., we do not attempt error recovery
  38.    on the stacks
  39. */
  40.  
  41.  
  42. #include "mawk.h"
  43. #include "jmp.h"
  44. #include "code.h"
  45. #include "sizes.h"
  46. #include "init.h"
  47. #include "memory.h"
  48.  
  49. extern unsigned compile_error_count ;
  50. #define error_state  (compile_error_count>0)
  51.  
  52.  
  53. /* a stack to hold jumps that need to be patched */
  54.  
  55. #define JMP_STK_SZ  (2*MAX_LOOP_DEPTH)
  56.  
  57. static INST **jmp_stack ; 
  58. static INST **jmp_sp  ;
  59.  
  60. /*-------------------------------------*/
  61. /* a stack to hold break or continue that need to be
  62.    patched (which is all of them) */
  63.  
  64. #define  BC_SZ    MAX_LOOP_DEPTH
  65.  
  66. /* the stack holds a linked list of these */
  67.  
  68. struct BC_node { /* struct for the break/continue list */
  69. char type ;   /*  'B' or 'C' */
  70. INST *jmp ;   /*  the jump to patch */
  71. struct BC_node *link ;
  72. } ;
  73.  
  74. static   struct BC_node  **BC_stack ;
  75. static   struct BC_node  **BC_sp ;
  76.  
  77. /*---------------------------------------*/
  78. /* a stack to hold some pieces of code while 
  79.    reorganizing loops */
  80.  
  81. #define  LOOP_CODE_SZ    (2*MAX_LOOP_DEPTH)
  82.  
  83. static struct loop_code {
  84. INST *code ;
  85. unsigned len ;
  86. }  *loop_code_stack , *lc_sp ;
  87.  
  88. /*--------------------------------------*/
  89. void jmp_stacks_init()
  90. { jmp_stack = (INST **)  zmalloc(JMP_STK_SZ*sizeof(INST*)) ;
  91.   jmp_sp = jmp_stack-1 ;
  92.  
  93.   BC_stack = (struct BC_node **) 
  94.               zmalloc(BC_SZ*sizeof(struct BC_node*)) ;
  95.   BC_sp =  BC_stack-1 ;
  96.  
  97.   loop_code_stack = (struct loop_code *)
  98.                     zmalloc(LOOP_CODE_SZ*sizeof(struct loop_code)) ;
  99.   lc_sp = loop_code_stack - 1 ;
  100. }
  101.  
  102. void jmp_stacks_cleanup()
  103. { zfree(jmp_stack, JMP_STK_SZ*sizeof(INST*)) ;
  104.   zfree(BC_stack, BC_SZ*sizeof(struct BC_node*)) ;
  105.   zfree(loop_code_stack, LOOP_CODE_SZ*sizeof(struct loop_code)) ;
  106. }
  107. /*--------------------------------------*/
  108. /* operations on the jmp_stack */
  109.  
  110. void code_jmp( jtype, target, expr_start)
  111.   int jtype ; 
  112.   INST *target ;
  113.   INST *expr_start ; /* used to recognize constant expressions,
  114.        which can only be _PUSHC , <address>  */
  115.   if (error_state)  return ;
  116.  
  117.   /* check if a constant expression will be at top of stack,
  118.      if so replace conditional jump with jump */
  119.  
  120.   if ( jtype != _JMP &&
  121.        code_ptr - 2 == expr_start &&
  122.        code_ptr[-2].op == _PUSHC )
  123.   { int t = test( (CELL *) code_ptr[-1].ptr ) ;
  124.     if ( jtype == _JZ && ! t ||
  125.          jtype == _JNZ && t )
  126.     { code_ptr -= 2 ; jtype = _JMP ; }
  127.   }
  128.    
  129.   if ( ! target ) /* jump will have to be patched later ,
  130.                      put it on the jmp_stack */
  131.   { if ( ++jmp_sp == jmp_stack + JMP_STK_SZ )
  132.           overflow("jmp stack" , JMP_STK_SZ ) ; 
  133.     *jmp_sp = code_ptr ;
  134.     code2(jtype, 0) ;
  135.   }
  136.   else
  137.   { INST *source = code_ptr ;
  138.   
  139.     code_ptr++->op = jtype ;
  140.     code_ptr++->op = target - source ; 
  141.   }
  142. }
  143.  
  144. void patch_jmp(target)  /* patch a jump on the jmp_stack */
  145.   INST *target ;
  146. { register INST *source ;
  147.  
  148.   if ( ! error_state )
  149.   {
  150.     if ( jmp_sp+1 <= jmp_stack ) bozo("jmp stack underflow") ;
  151.     source = *jmp_sp-- ;
  152.     source[1].op = target - source ;
  153.   }
  154. }
  155.  
  156.  
  157. /*---------------------------*/
  158.  
  159. /* a stack of linked lists of BC_nodes for patching 
  160.    break and continue statements.  */
  161.  
  162.  
  163. void BC_new()  /* push an empty list on the stack */
  164.   if ( ! error_state )
  165.   { if ( ++BC_sp == BC_stack + BC_SZ ) overflow("BC stack", BC_SZ) ;
  166.     * BC_sp = (struct BC_node *) 0 ;
  167.   }
  168. }
  169.  
  170. void BC_insert(type, address)
  171.   int type ; INST *address ;
  172. { register struct BC_node *p ; 
  173.  
  174.   if ( error_state )  return ;
  175.   if ( BC_sp <= BC_stack - 1 )
  176.   {  compile_error(  type == 'B' ?
  177.         "break statement outside of loop" :
  178.         "continue statement outside of loop" ) ; 
  179.      return ;
  180.   }
  181.   
  182.   p = (struct BC_node *) zmalloc( sizeof(struct BC_node) ) ;
  183.   p->type = type ; p->jmp = address ;
  184.   p->link = *BC_sp ; *BC_sp = p ;
  185. }
  186.  
  187. void BC_clear(B_address, C_address)  
  188. /* patch all break and continues on list */
  189. INST *B_address, *C_address ;
  190. { register struct BC_node *p , *q ;
  191.  
  192.   if (error_state) return ;
  193.   if ( BC_sp+1 <= BC_stack ) bozo("underflow on BC stack") ;
  194.   p = *BC_sp-- ;
  195.   while ( p )
  196.   { p->jmp[1].op = (p->type=='B' ? B_address : C_address) - p->jmp ;
  197.     q = p ; p = p->link ; zfree(q, sizeof(struct BC_node)) ;
  198.   }
  199. }
  200.  
  201. /*---------------------------------------------*/
  202. /*  save and restore some code for reorganizing
  203.     loops on a stack */
  204.  
  205.  
  206. void code_push( p, len)
  207.   INST *p ; unsigned len ;
  208.   if (error_state) return ;
  209.   if ( ++lc_sp == loop_code_stack + LOOP_CODE_SZ )
  210.         overflow("loop_code_stack" , LOOP_CODE_SZ) ;
  211.  
  212.   if ( len )
  213.   { lc_sp->code = (INST *) zmalloc(sizeof(INST) * len) ;
  214.     (void) memcpy(lc_sp->code, p, SIZE_T(sizeof(INST) * len)) ; }
  215.   else  lc_sp->code = (INST *) 0 ;
  216.   lc_sp->len = len ;
  217. }
  218.  
  219. /* copy the code at the top of the loop code stack to target.
  220.    return the number of bytes moved */
  221.  
  222. unsigned code_pop(target) 
  223.   INST *target ;
  224.   if (error_state)  return 0 ;
  225.   if ( lc_sp+1 <= loop_code_stack )  bozo("loop code stack underflow") ;
  226.   if ( lc_sp->len )
  227.   { (void) memcpy(target, lc_sp->code, SIZE_T(lc_sp->len * sizeof(INST))) ;
  228.     zfree(lc_sp->code, sizeof(INST)*lc_sp->len) ; }
  229.   return lc_sp-- -> len ;
  230. }
  231.